xpk.Hint = function(elements, options){
	
	var mouseMove = function(event){
		if(_this.mouseOver) {
			_this.mouse = {
				x: event.pageX,
				y: event.pageY
			};
		};
	};
	
	var _body = $(document);
	
	var _this = {
		options: {
			opacity: 0.9,
			width: 200,
			delay: 250,
			position: 'right' // top | left | bottom | right | mouse
		},
		activeElement: null,
		setOptions: function(options){
			$.extend(this.options, options || {});
		},			 
		init: function(){
			this.setOptions(options);
			
			var tipHTML = 	'<div class="hint-body" id="tip-body">\
					<div class="hint-content"></div>\
					</div><div class="hint-corner"></div>';
			
			this.toolTip = $('<div></div>', {
					 	className: 'hint-wrap'
					}).css({
					'position': 'absolute',
					'bottom': '0',					
					'visibility': 'hidden',
//					'opacity': this.options.opacity,
					'zIndex': 1000
				}).appendTo(document.body).html(tipHTML);

			
			this.content = this.toolTip.find('div.hint-content');
			this.body = this.toolTip.find('div.hint-body');
			this.corner = this.toolTip.find('div.hint-corner');

			this.build(elements);
			if(this.options.init) this.options.init.call(this);	
			return this;
		},
		
		build: function(elements){
			
			if(!elements || !elements.length) {
				return this;
			};

			var selector = this.options.fromSelector;
			var activeElement = [];
			
			elements.delegate(selector, 'mouseenter', function(event){
				var $element = $(this);
				_this.mover($element, event);
				activeElement = $element;
			});
			elements.delegate(selector, 'mouseleave',function(event){
				_this.mout(activeElement, event);
			});

			_body.click(function(){
				_this.mout(_this.$activeElement);
				_this.hide();
			});

			
		},
		mover: function(element, event){
			
			if(this.disabled) return;
			
			var $element = $(element);
			window.clearTimeout(this.showTimer);

			
			var html = $element.data('_tooltip_html');
			if(!html) {
				html = $element[0].title;
				$element[0].title = '';
			};
			
			if(typeof this.options.source == 'function'){
				html = this.options.source.apply(this, [$element]);
			};
			
			if(!html) {
				this.mouseOver = 0;
				return false;
			};
			$element.data('_tooltip_html', html);

			this.showTimer = window.setTimeout(function(){
				_this.show($element, html, event);
			}, this.options.delay);
			
			this.mouseOver = 1;
		},
		
		mout: function(element, event){
			if(this.disabled) return;
			window.clearTimeout(this.showTimer);
			this.mouseOver = 0;
			this.hide();
		},

		show: function($element, html, event){
			if(!this.mouseOver) return false;
			
			if(!html) {
				var html = $element.data('_tooltip_html');
			};
				
			this.content.html(html).css('visibility', 'hidden');
			this.toolTip.css({'width': ''});
			this.body.css({'width': '', 'height': ''});
			
			
			this.width = this.body.width(); // we'll use it later to properly position tooltip
			if(this.width > this.options.width) {
				this.width = this.options.width;
				this.body.css({'width': this.width});
			};
			this.height = this.body.height(); // we'll use it later to properly position tooltip
			
			this.setTipPosition($element, event);
			var _bodyCss = {
				'width': 0,
				'height': 0,
				'opacity': 0
				};
			if(window.ie){
				delete _bodyCss.opacity;
			};
			this.body.css(_bodyCss);
			
			this.corner.css('visibility', 'hidden');
			
			this.toolTip.css({
				'width': this.options.width,
				'visibility': 'visible'
			});
			
			_bodyCss = {
				'width': this.width + 2,
				'height': this.height + 2,
				'opacity': this.options.opacity
				};
			if(window.ie){
				delete _bodyCss.opacity;
			};
			this.body.animate(_bodyCss, {
				duration: 150,
				complete: function(){
					_this.corner.css('visibility', '');
					_this.content.css('visibility', '');
				}
			});

			this.activeElement = $element[0];
			this.$activeElement = $element;

		},
		hide: function($element){
			if(!this.activeElement) {
				return false;
			};
			this.corner.css('visibility', 'hidden');
			this.toolTip.css({
					'visibility': 'hidden',
					'bottom': 'auto',
					'top': -1000,
					'left': -1000
				});
			this.activeElement = this.$activeElement = null;

		},
		getElementPosition: function($element){
			var element = $element[0];
			var position = $element.offset()
			
			var obj = {
				'width': element.offsetWidth,
				'height': element.offsetHeight,
				'left': position.left,
				'top': position.top
			};
			obj.right = obj.left + obj.width;
			obj.bottom = obj.top + obj.height;
			return obj;
		},
		setTipPosition: function(element){
			var position = this.getElementPosition(element);
			
			this.elementPosition = position;

			var _winHeight = $(document.body).innerHeight();
			var _css = {
				top: 'auto',
				left: 'auto',			
				bottom:  _winHeight - position.top + 3,
				left: position.left - this.options.width / 2 + position.width / 2
			};
			this.toolTip.css(_css);
		},
		disable: function(){
			window.clearTimeout(this.showTimer);
			this.hide();
			this.disabled = 1;
		},
		enable: function(){
			this.disabled = 0;
		}

	};

	return _this.init();
};